var util        = require('util'),
    helper      = require('../utils/helper'),
    dateformat  = require('dateformat');

function CacheRedis(cfg, pool, log, defaultExpireSeconds) {
    if (!cfg || !pool || !log) {
        throw new Error("Config and connection vars, and log function are required.");
    }
    this.config = cfg;
    this.pool = pool;
    this.log = log;
    this.expireSeconds = defaultExpireSeconds || 60;
}

CacheRedis.prototype.putItem = function(item, callback) {
    var that = this;
    var itemId = item[ item.getEntityIndex() ];
    var cacheKey = item.getEntityName() + ':' + itemId;
    var cacheValue = JSON.stringify(item || {});
    this.log('cache putItem(): key = ' + cacheKey + ' value = ...');
    that.pool.acquire(function(err, client) {
    	client.multi()
        .set(cacheKey, cacheValue)
        .expire(cacheKey, item.getEntityExpiration() || that.expireSeconds)
        .exec(function (err, results) {
			if (err) {
			 that.log('Error: putItem(): ' + err);
			}
			if (callback) {
			 callback(err, item);
			}
			that.pool.release(client);
			return item;
		});
    });
};

CacheRedis.prototype.putItemByClass = function(itemClass, item, callback) {
    var that = this;
    var itemId = item[ itemClass.entityIndex ];
    var cacheKey = itemClass.entityName + ':' + itemId;
    var cacheValue = JSON.stringify(item || {});
    this.log('cache putItemByClass(): key = ' + cacheKey + ' value = ...');
    that.pool.acquire(function(err, client) {
    	client.multi()
       .set(cacheKey, cacheValue)
       .expire(cacheKey,  itemClass.entityExpiration || that.expireSeconds)
       .exec(function (err, results) {
	        if (err) {
	            that.log('Error: putItemByClass(): ' + err);
	        }
	        if (callback) {
	            callback(err, item);
	        }
	        that.pool.release(client);
	        return item;
	    });
    });
};

CacheRedis.prototype.putItemByProperty = function(itemClass,property,item, callback) {
    var that = this;
    var cacheKey = itemClass.entityName + ':' + property;
    var cacheValue = JSON.stringify(item || {});
    this.log('cache putItemByClass(): key = ' + cacheKey + ' value = ...');
    that.pool.acquire(function(err, client) {
    	client.multi()
       .set(cacheKey, cacheValue)
       .expire(cacheKey,  itemClass.entityExpiration || that.expireSeconds)
       .exec(function (err, results) {
	        if (err) {
	            that.log('Error: putItemByClass(): ' + err);
	        }
	        if (callback) {
	            callback(err, item);
	        }
	        that.pool.release(client);
	        return item;
	    });
    });
};



CacheRedis.prototype.delItem = function(itemClass, itemId, callback) {
    var that = this;
    var cacheKey = itemClass.entityName + ':' + itemId;
    this.log('cache delItem(): key = ' + cacheKey);
    that.pool.acquire(function(err, client) {
    	client.del(cacheKey, function (err) {
	        if (err) {
	            that.log('Error: delItem(): ' + err);
	        }
	        if (callback) {
	            callback(err, null);
	        }
	        that.pool.release(client);
	        return null;
	    });
    });
};

CacheRedis.prototype.delItems = function(itemClass, callback) {
    var that = this;
    var cacheKey = itemClass.entityName + ':*';
    this.log('cache delItems(): key = ' + cacheKey);
    
    that.pool.acquire(function(err, client) {
    	var c=client;
    	client.KEYS(cacheKey,function(err,result){
	    	if(err){
	    		that.log('Error: delItems(): ' + err);
	    	}
	    	for(var i=0;i<result.length;i++){
	    		var key=result[i];
	    		that.log('DEL: ' + key);
	    		c.del(key, function (err) {
			        if (err) {
			            that.log('Error: delItem(): ' + err);
			        }
			        if (callback) {
			            callback(err, null);
			        }
			        return null;
	    		});
	    	}
	    	that.pool.release(client);
	    	return null;
	    });
    });
};

CacheRedis.prototype.putItems = function(itemClass, items, callback) {
    var that = this;
    var cacheKey = itemClass.entityName + ':*';
    var cacheValue = JSON.stringify(items || {});
    this.log('cache putItems(): key = ' + cacheKey+ ' value = ...');
    that.pool.acquire(function(err, client) {
	    	client.multi()
	       .set(cacheKey, cacheValue)
	       .expire(cacheKey, itemClass.entityExpiration || that.expireSeconds)
	       .exec(function (err, results) {
	        if (err) {
	            that.log('Error: putItems(): ' + err);
	        }
	        if (callback) {
	            callback(err, items);
	        }
	        that.pool.release(client);
	        return items;
	    });
    });
};

CacheRedis.prototype.getItem = function(itemClass, itemId, callback) {
    var that = this;
    var cacheKey = itemClass.entityName + ':' + itemId;
    this.log('cache getItem(): key = ' + cacheKey);
    that.pool.acquire(function(err, client) {
    	client.get(cacheKey, function (err, result) {
	        that.log('cache getItem(): key = ' + cacheKey + ' : ' + (result ? 'HIT' : 'MISS'));
	        if (err) {
	            that.log('Error: getItem(): ' + err);
	        }
	        if (callback) {
	            callback(err, result ? JSON.parse(result) : null);
	        }
	        that.pool.release(client);
	        return result;
	    });
    });
};

CacheRedis.prototype.getItems = function(itemClass, callback) {
    var that = this;
    var cacheKey = itemClass.entityName + ':*';
    this.log('cache getItems(): key = ' + cacheKey);
    that.pool.acquire(function(err, client) {
    	client.get(cacheKey, function (err, result) {
	        that.log('cache getItems(): key = ' + cacheKey + ' : ' + (result ? 'HIT' : 'MISS'));
	        if (err) {
	            that.log('Error: getItems(): ' + err);
	        }
	        if (callback) {
	            callback(err, result ? JSON.parse(result) : null);
	        }
	        that.pool.release(client);
	        return result;
	    });
    });
};

CacheRedis.prototype.putSearch = function(itemClass,search,items, callback) {
    var that = this;
    var cacheKey = itemClass.entityName + ':'+search;
    var cacheValue = JSON.stringify(items || {});
    this.log('cache putSearch(): key = ' + cacheKey+ ' value = ...');
    that.pool.acquire(function(err, client) {
    		client.multi()
	       .set(cacheKey, cacheValue)
	       .expire(cacheKey, itemClass.entityExpiration || that.expireSeconds)
	       .exec(function (err, results) {
	        if (err) {
	            that.log('Error: putItems(): ' + err);
	        }
	        if (callback) {
	            callback(err, items);
	        }
	        that.pool.release(client);
	        return items;
	    });
    });
};

CacheRedis.prototype.search = function(itemClass,search, callback) {
	var that = this;
    var cacheKey = itemClass.entityName + ':'+search;
    this.log('cache getSearch(): key = ' + cacheKey);
    that.pool.acquire(function(err, client) {
    	client.get(cacheKey, function (err, result) {
	        that.log('cache getSearch(): key = ' + cacheKey + ' : ' + (result ? 'HIT' : 'MISS'));
	        if (err) {
	            that.log('Error: getSearch(): ' + err);
	        }
	        if (callback) {
	            callback(err, result ? JSON.parse(result) : null);
	        }
	        that.pool.release(client);
	        return result;
	    });
    });
};


module.exports.CacheRedis = CacheRedis;